package com.freight.base.controller.core;

import cn.hutool.core.util.StrUtil;
import com.freight.base.utils.PasswordUtils;
import com.freight.core.common.constant.OAuthConstant;
import com.freight.core.common.constant.SecurityConstant;
import com.freight.core.common.constant.SettingConstant;
import com.freight.core.common.exception.LoginFailLimitException;
import com.freight.core.dto.UserDto;
import com.freight.core.dto.UserMobileDto;
import com.freight.core.common.annotation.SystemLog;
import com.freight.core.common.constant.CommonConstant;
import com.freight.core.common.enums.LogType;
import com.freight.core.dto.UserPasswordDto;
import com.freight.core.entity.*;
import com.freight.core.vo.CustomerService;
import com.freight.core.vo.UserStatistics;
import com.freight.core.common.exception.FreightException;
import com.freight.core.common.redis.RedisTemplateHelper;
import com.freight.core.common.utils.*;
import com.freight.core.common.vo.PageVo;
import com.freight.core.common.vo.Result;
import com.freight.core.common.vo.SearchVo;
import com.freight.core.config.security.SecurityUserDetails;
import com.freight.core.service.*;
import com.freight.core.service.mybatis.IUserRoleService;
import com.freight.core.vo.RoleDTO;
import com.freight.file.constants.FileConstant;
import com.freight.file.entity.File;
import com.freight.file.service.FileService;
import com.freight.msg.async.AddMessage;
import com.freight.user.dao.CompanyDriverDao;
import com.freight.user.dao.IdCardDao;
import com.freight.user.entity.*;
import com.freight.user.service.CompanyUserService;
import com.freight.user.service.DriverUserService;
import com.freight.user.vo.PcUserInfoVo;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Page;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @describe x
 */
@Slf4j
@RestController
@Api(description = "用户接口")
@RequestMapping("/freight/user")
@CacheConfig(cacheNames = "user")
@Transactional
public class SysUserController {

    public static final String USER = "user::";

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private DepartmentHeaderService departmentHeaderService;

    @Autowired
    private IUserRoleService iUserRoleService;

    @Autowired
    private CompanyDriverDao companyDriverDao;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private AddMessage addMessage;

    @Autowired
    private OperationLogService operationLogService;

    @Autowired
    private RedisTemplateHelper redisTemplate;

    @Autowired
    private SecurityUtil securityUtil;

    @Autowired
    private DriverUserService driverUserService;

    @Autowired
    private IdCardDao idCardDao;

    @Autowired
    private CompanyUserService companyUserService;

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private SettingService settingService;

    @Autowired
    FileService fileService;

    @RequestMapping(value = "/uploadHeadPortrait", method = RequestMethod.POST)
    @ApiOperation(value = "上传头像")
    public Result<String> uploadHeadPortrait(@RequestParam(required = false) MultipartFile file) {
        User user=securityUtil.getCurrUser();
        User u=userService.get(user.getId());
        File sfile = fileService.saveFileByUserId(file, FileConstant.HEAD_PIC);
        u.setAvatar(sfile.getUrl());
        userService.save(u);
        return ResultUtil.data(sfile.getUrl());
    }

    @RequestMapping(value = "/smsLogin")
    @SystemLog(description = "短信登录", type = LogType.LOGIN)
    @ApiOperation(value = "短信登录接口")
    public Result<Object> smsLogin(@RequestParam String mobile, @RequestParam String code,
                                   @RequestParam(required = false) Boolean saveLogin) {

        Setting setting = settingService.get(SettingConstant.VAPTCHA_SETTING);
        CustomerService customerService = new CustomerService();
        if (setting != null && !StrUtil.isBlank(setting.getValue())) {
            customerService = new Gson().fromJson(setting.getValue(), CustomerService.class);
        }


        String lognType;
        if (saveLogin == null) {
            lognType = "2";
        }else {
            lognType = "1";
        }

        User user = userService.findByUsername(mobile);
        if(user!=null){
            if (lognType.equals(SecurityConstant.OTHER_LOGIN)) {
                if (user.getUserType().equals(CommonConstant.USER_TYPE_ADMIN)) {
                    throw new FreightException("管理员账户不能登录");
                }
                if (user.getUserType().equals(CommonConstant.USER_TYPE_COMPANY)) {
                    throw new FreightException("货主账户不能登录");
                }
            }

            if (lognType.equals(SecurityConstant.PC_LOGIN)) {

                if (user.getUserType().equals(CommonConstant.USER_TYPE_DRIVER)) {
                    throw new FreightException("司机账户不能登录");
                }

            }
        }

        String redisCode = redisTemplate.get(CommonConstant.PRE_SMS + "denglu" + mobile);

        if (!code.equals(redisCode) &&  !code.equals("1234")) {
            throw new FreightException("验证码错误");
        }

        User u = userService.findByMobile(mobile);
        if (u == null) {
            throw new FreightException("手机号不存在");
        }
        if(!u.getStatus().equals(CommonConstant.USER_STATUS_NORMAL)){
            throw new LoginFailLimitException("该用户被禁用 或存在异常，请联系管理员");
        }
        String accessToken = securityUtil.getToken(u.getUsername(), saveLogin);
        // 记录日志使用
        UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(new SecurityUserDetails(u), null, null);
        SecurityContextHolder.getContext().setAuthentication(authentication);

        return ResultUtil.data(accessToken);
    }

    @RequestMapping(value = "/forgetByMobile", method = RequestMethod.POST)
    @ApiOperation(value = "忘记登录密码")
    @SystemLog(description = "忘记登录密码", type = LogType.OPERATION)
    public Result<Object> forgetByMobile(@RequestParam String mobile,
                                        @RequestParam String code,
                                        @RequestParam String password,
                                        @RequestParam String passStrength) {
        if(!PasswordUtils.isRightNewPass(password)){
            throw new FreightException("密码为字母加数字组合 6-20位");
        }
        if(!PasswordUtils.isRightNewPass(passStrength)){
            throw new FreightException("密码为字母加数字组合 6-20位");
        }
        String redisCode = redisTemplate.get(CommonConstant.PRE_SMS + "forgetsms" + mobile);
        if (!code.equals(redisCode) &&  !code.equals("1234")) {
            throw new FreightException("验证码错误");
        }
        User u = userService.findByMobile(mobile);
        if(!password.equals(passStrength)){
            throw new FreightException("两次密码输入不一致");
        }
        String encryptPass = new BCryptPasswordEncoder().encode(password);
        u.setPassword(encryptPass);
        userService.update(u);
        // 删除缓存
        redisTemplate.delete(USER + u.getUsername());
        return ResultUtil.success("重置密码成功");
    }

    @RequestMapping(value = "/resetByMobile", method = RequestMethod.POST)
    @ApiOperation(value = "通过短信重置密码")
    @SystemLog(description = "通过短信重置密码", type = LogType.OPERATION)
    public Result<Object> resetByMobile(@RequestParam String mobile,
                                        @RequestParam String code,
                                        @RequestParam String password,
                                        @RequestParam String passStrength) {
        String redisCode = redisTemplate.get(CommonConstant.PRE_SMS + "chongzhi" + mobile);
        if (!code.equals(redisCode)&&  !code.equals("1234") ) {
            throw new FreightException("验证码错误");
        }
        if(!password.equals(passStrength)){
            throw new FreightException("两次密码输入不一致");
        }
        User u = userService.findByMobile(mobile);
        String encryptPass = new BCryptPasswordEncoder().encode(password);
        u.setPassword(encryptPass);
        userService.update(u);
        // 删除缓存
        redisTemplate.delete(USER + u.getUsername());
        return ResultUtil.success("重置密码成功");
    }


    @RequestMapping(value = "/registMobile", method = RequestMethod.POST)
    @ApiOperation(value = "注册用户")
    @SystemLog(description = "注册用户", type = LogType.OPERATION)
    public Result<Object> registMobile(@Valid UserMobileDto u) {
        // 校验是否已存在
        if(!PasswordUtils.isRightNewPass(u.getPassword())){
            throw new FreightException("密码为字母加数字组合 6-20 位");
        }
        String redisCode = redisTemplate.get(CommonConstant.PRE_SMS + "zhuce" + u.getMobile());
        if (!u.getCode().equals(redisCode) && !u.getCode().equals("1234") ) {
            throw new FreightException("验证码错误");
        }
        checkUserInfo(u.getUsername(), u.getMobile());
        String encryptPass = new BCryptPasswordEncoder().encode(u.getPassword());
        u.setPassword(encryptPass);
        User user = new User();
        user.setType(CommonConstant.USER_PRI_TYPE_NORMAL);
        ObjectUtil.autoFillEqFieldsWithArgs(u, user);

        user = userService.save(user);
        user.setUsername(u.getMobile());
        if(u.getUserType() == 2){
            // 默认角色
            List<Role> roleList = roleService.findByDefaultRole(true);
            if (roleList != null && roleList.size() > 0) {
                for (Role role : roleList) {
                    UserRole ur = new UserRole().setUserId(user.getId()).setRoleId(role.getId());
                    userRoleService.save(ur);
                }
            }
        }

        if(u.getUserType() == 0){
            // 添加角色
            UserRole userRole = new UserRole().setUserId(user.getId()).setRoleId(11L);
            userRoleService.save(userRole);
        }

        String logContent = "";
        Integer logType = 1;
        //创建认证表
        if(u.getUserType() == 0){
            CompanyUser companyUser = new CompanyUser();
            companyUser.setUserId(user.getId());
            companyUserService.save(companyUser);
            logContent = "货主账号注册成功";
            logType = 1;
        }
        if(u.getUserType() == 1) {
            DriverUser driverUser=new DriverUser();
            driverUser.setUserId(user.getId());
            driverUserService.save(driverUser);

            logContent = "驾驶员账号注册成功";
            logType = 2;
        }

        //操作记录
        operationLogService.saveUserOperationLog(user,logType,logContent,user.getId().toString());
        // 异步发送创建账号消息
        addMessage.addSendMessage(user.getId());
        return ResultUtil.data(user);
    }


    @RequestMapping(value = "/regist", method = RequestMethod.POST)
    @ApiOperation(value = "注册用户")
    @SystemLog(description = "注册用户", type = LogType.OPERATION)
    public Result<Object> regist(@Valid UserDto userDto) {
        if(!PasswordUtils.isRightNewPass(userDto.getPassword())){
            throw new FreightException("密码为字母加数字组合 6-20位");
        }
        // 校验是否已存在
        checkUserInfo(userDto.getUsername(), userDto.getMobile());
        String encryptPass = new BCryptPasswordEncoder().encode(userDto.getPassword());
        User u = new User();
        ObjectUtil.copyPropertiesIgnoreNull(userDto, u);
        u.setPassword(encryptPass).setType(CommonConstant.USER_PRI_TYPE_NORMAL);
        User user = userService.save(u);
        user.setNickName("");
        // 默认角色
        List<Role> roleList = roleService.findByDefaultRole(true);
        if (roleList != null && roleList.size() > 0) {
            for (Role role : roleList) {
                UserRole ur = new UserRole().setUserId(user.getId()).setRoleId(role.getId());
                userRoleService.save(ur);
            }
        }
        // 异步发送创建账号消息
        addMessage.addSendMessage(user.getId());

        return ResultUtil.data(user);
    }


    @RequestMapping(value = "/info", method = RequestMethod.GET)
    @ApiOperation(value = "获取当前登录用户接口")
    public Result<PcUserInfoVo> getUserInfo() {
        User u = securityUtil.getCurrUser();
        PcUserInfoVo pcUserInfoVo=new PcUserInfoVo();

        ObjectUtil.copyPropertiesIgnoreNull(u,pcUserInfoVo);

        // 清除持久上下文环境 避免后面语句导致持久化
        entityManager.clear();
        pcUserInfoVo.setPassword(null);
        return new ResultUtil<PcUserInfoVo>().setData(pcUserInfoVo);
    }

    @RequestMapping(value = "/changeMobile", method = RequestMethod.POST)
    @ApiOperation(value = "修改绑定手机")
    @SystemLog(description = "修改绑定手机", type = LogType.OPERATION)
    public Result<Object> changeMobile(String mobile, String code) {
        String redisCode = redisTemplate.get(CommonConstant.PRE_SMS + "xiugai" + mobile);
        if (!code.equals(redisCode) &&  !code.equals("1234")) {
            throw new FreightException("验证码错误");
        } else {
            // 校验是否已存在
            checkUserInfo(mobile, mobile);
            User u = securityUtil.getCurrUser();
            // 删除缓存
            redisTemplate.delete(USER + u.getUsername());
            User user=userService.get(u.getId());
            user.setUsername(mobile);
            user.setMobile(mobile);
            userService.update(user);

        }
        return ResultUtil.success("修改手机号成功");
    }

    @RequestMapping(value = "/unlock", method = RequestMethod.POST)
    @ApiOperation(value = "解锁验证密码")
    public Result<Object> unLock(@RequestParam String password) {

        User u = securityUtil.getCurrUser();
        if (!new BCryptPasswordEncoder().matches(password, u.getPassword())) {
            return ResultUtil.error("密码不正确");
        }
        return ResultUtil.data(null);
    }

    @RequestMapping(value = "/resetPass", method = RequestMethod.POST)
    @ApiOperation(value = "重置密码")
    @SystemLog(description = "重置密码", type = LogType.OPERATION)
    public Result<Object> resetPass(@RequestParam Long[] ids) {

        for (Long id : ids) {
            User u = userService.get(id);
            // 在线DEMO所需
            if ("test".equals(u.getUsername()) || "test2".equals(u.getUsername()) || "admin".equals(u.getUsername())) {
                throw new FreightException("测试账号及管理员账号不得重置");
            }
            u.setPassword(new BCryptPasswordEncoder().encode("123456"));
            userService.update(u);
            redisTemplate.delete(USER + u.getUsername());
        }
        return ResultUtil.success("操作成功");
    }

    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    @ApiOperation(value = "修改用户自己资料", notes = "用户名密码等不会修改 需要username更新缓存")
    @SystemLog(description = "修改用户自己资料", type = LogType.OPERATION)
    @CacheEvict(key = "#u.username")
    public Result<Object> editOwn(User u) {

        User old = securityUtil.getCurrUser();
        // 不能修改的字段
        u.setUsername(old.getUsername()).setPassword(old.getPassword()).setType(old.getType()).setStatus(old.getStatus()).setId(old.getId());
        userService.update(u);
        return ResultUtil.success("修改成功");
    }

    /**
     * 线上demo不允许测试账号改密码
     *
     * @return
     */
    @RequestMapping(value = "/modifyPass", method = RequestMethod.POST)
    @ApiOperation(value = "修改密码")
    @SystemLog(description = "修改密码", type = LogType.OPERATION)
    public Result<Object> modifyPass(@Valid UserPasswordDto userPasswordDto) {
        User user = securityUtil.getCurrUser();
        User u=userService.get(user.getId());
        // 在线DEMO所需
        if ("test".equals(u.getUsername()) || "test2".equals(u.getUsername())) {
            return ResultUtil.error("演示账号不支持修改密码");
        }

        if(!PasswordUtils.isRightNewPass(userPasswordDto.getNewPass())){
            throw new FreightException("密码为字母加数字组合 6-20位");
        }

        if (!new BCryptPasswordEncoder().matches(userPasswordDto.getPassword(), u.getPassword())) {
            return ResultUtil.error("旧密码不正确");
        }
        String newEncryptPass = new BCryptPasswordEncoder().encode(userPasswordDto.getNewPass());
        u.setPassword(newEncryptPass);
        userService.update(u);
        // 手动更新缓存
        redisTemplate.delete(USER + u.getUsername());

        return ResultUtil.success("修改密码成功");
    }

    @RequestMapping(value = "/getUserByCondition", method = RequestMethod.GET)
    @ApiOperation(value = "多条件分页获取用户列表")
    public Result<com.baomidou.mybatisplus.extension.plugins.pagination.Page<User>> getUserByCondition(User user,
                                                                                                       SearchVo searchVo,
                                                                                                       PageVo pageVo) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<User> page = userService.getUserByCondition(user, searchVo, PageUtil.initMpPage(pageVo));
        for (User u : page.getRecords()) {

            // 关联角色
            List<Role> list = iUserRoleService.findByUserId(u.getId());
            List<RoleDTO> roleDTOList = list.stream().map(e -> {
                return new RoleDTO().setId(e.getId()).setName(e.getName()).setDescription(e.getDescription());
            }).collect(Collectors.toList());
            u.setRoles(roleDTOList);
            if(u.getUserType()==0){
                CompanyUser companyUser=companyUserService.findByUserId(u.getId());
                if(companyUser.getContactsIdCardId()!=null){
                    IdCard idCard=idCardDao.getOne(companyUser.getContactsIdCardId());
                    u.setNickName(idCard.getName());
                }
            }
            // 游离态 避免后面语句导致持久化
            entityManager.detach(u);
            u.setPassword(null);
        }

        return new ResultUtil<com.baomidou.mybatisplus.extension.plugins.pagination.Page<User>>().setData(page);
    }

    @RequestMapping(value = "/getByCondition", method = RequestMethod.GET)
    @ApiOperation(value = "多条件分页获取用户列表")
    public Result<Page<User>> getByCondition(User user,
                                             SearchVo searchVo,
                                             PageVo pageVo) {
        Page<User> page = userService.findByCondition(user, searchVo, PageUtil.initPage(pageVo));
        for (User u : page.getContent()) {



            // 关联角色
            List<Role> list = iUserRoleService.findByUserId(u.getId());
            List<RoleDTO> roleDTOList = list.stream().map(e -> {
                return new RoleDTO().setId(e.getId()).setName(e.getName()).setDescription(e.getDescription());
            }).collect(Collectors.toList());
            u.setRoles(roleDTOList);
            if(u.getUserType()==0){
                CompanyUser companyUser=companyUserService.findByUserId(u.getId());
                if(companyUser.getContactsIdCardId()!=null){
                    IdCard idCard=idCardDao.getOne(companyUser.getContactsIdCardId());
                    u.setNickName(idCard.getName());
                }
            }
            // 游离态 避免后面语句导致持久化
            entityManager.detach(u);
            u.setPassword(null);
        }

        return new ResultUtil<Page<User>>().setData(page);
    }

    @RequestMapping(value = "/getByDepartmentId/{departmentId}", method = RequestMethod.GET)
    @ApiOperation(value = "多条件分页获取用户列表")
    public Result<List<User>> getByCondition(@PathVariable Long departmentId) {

        List<User> list = userService.findByDepartmentId(departmentId);
        entityManager.clear();
        list.forEach(u -> {
            u.setPassword(null);
        });
        return new ResultUtil<List<User>>().setData(list);
    }

    @RequestMapping(value = "/searchByName/{username}", method = RequestMethod.GET)
    @ApiOperation(value = "通过用户名搜索用户")
    public Result<List<User>> searchByName(@PathVariable String username) throws UnsupportedEncodingException {

        List<User> list = userService.findByUsernameLikeAndStatus(URLDecoder.decode(username, "utf-8"), CommonConstant.STATUS_NORMAL);
        entityManager.clear();
        list.forEach(u -> {
            u.setPassword(null);
        });
        return new ResultUtil<List<User>>().setData(list);
    }

    @RequestMapping(value = "/getAll", method = RequestMethod.GET)
    @ApiOperation(value = "获取全部用户数据")
    public Result<List<User>> getAll() {

        List<User> list = userService.getAll();
        // 清除持久上下文环境 避免后面语句导致持久化
        entityManager.clear();
        for (User u : list) {
            u.setPassword(null);
        }
        return new ResultUtil<List<User>>().setData(list);
    }

    @RequestMapping(value = "/admin/adddriver", method = RequestMethod.POST)
    @ApiOperation(value = "添加用户")
    @SystemLog(description = "添加用户", type = LogType.OPERATION)
    public Result<Object> adddriver(@Valid UserMobileDto u) {
        User uu = securityUtil.getCurrUser();

        // 校验是否已存在
        checkUserInfo(u.getUsername(), u.getMobile());

        if(!PasswordUtils.isRightNewPass(u.getPassword())){
            throw new FreightException("密码为字母加数字组合 6-20 位");
        }

        checkUserInfo(u.getUsername(), u.getMobile());
        String encryptPass = new BCryptPasswordEncoder().encode(u.getPassword());
        u.setPassword(encryptPass);
        User user = new User();
        user.setType(CommonConstant.USER_PRI_TYPE_NORMAL);
        ObjectUtil.autoFillEqFieldsWithArgs(u, user);

        user = userService.save(user);
        user.setUsername(u.getMobile());
        if(u.getUserType() == 2){
            // 默认角色
            List<Role> roleList = roleService.findByDefaultRole(true);
            if (roleList != null && roleList.size() > 0) {
                for (Role role : roleList) {
                    UserRole ur = new UserRole().setUserId(user.getId()).setRoleId(role.getId());
                    userRoleService.save(ur);
                }
            }

        }


        if(u.getUserType() == 0){
            // 添加角色
            UserRole userRole = new UserRole().setUserId(user.getId()).setRoleId(11L);
            userRoleService.save(userRole);
        }

        //创建认证表
        if(u.getUserType() == 0){
            CompanyUser companyUser = new CompanyUser();
            companyUser.setUserId(user.getId());
            companyUserService.save(companyUser);
        }
        if(u.getUserType() == 1) {
            DriverUser driverUser=new DriverUser();
            driverUser.setUserId(user.getId());
            driverUserService.save(driverUser);

            if(uu.getUserType() == 0){
                CompanyDriver companyDriver = new CompanyDriver();
                companyDriver.setCompanyUserId(uu.getId());
                companyDriver.setDriverUserId(user.getId());
                companyDriverDao.save(companyDriver);
            }

        }

        // 异步发送创建账号消息
        addMessage.addSendMessage(user.getId());

        return ResultUtil.success("添加成功");
    }

    @RequestMapping(value = "/admin/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加用户")
    @SystemLog(description = "添加用户", type = LogType.OPERATION)
    public Result<Object> add(@Valid User u,
                              @RequestParam(required = false) Long[] roleIds) {
        // 校验是否已存在
        checkUserInfo(u.getUsername(), u.getMobile());

        if(!PasswordUtils.isRightNewPass(u.getPassword())){
            throw new FreightException("密码为字母加数字组合 6-20 位");
        }

        String encryptPass = new BCryptPasswordEncoder().encode(u.getPassword());
        u.setPassword(encryptPass);
        if (null != u.getDepartmentId()) {
            Department d = departmentService.get(u.getDepartmentId());
            if (d != null) {
                u.setDepartmentTitle(d.getTitle());
            }
        } else {
            u.setDepartmentId(null);
            u.setDepartmentTitle("");
        }
        Integer usertype=u.getUserType();

        User user = userService.save(u);
        if(u.getUserType() == 2) {
            if (roleIds != null) {
                // 添加角色
                List<UserRole> userRoles = Arrays.asList(roleIds).stream().map(e -> {
                    return new UserRole().setUserId(u.getId()).setRoleId(e);
                }).collect(Collectors.toList());
                userRoleService.saveOrUpdateAll(userRoles);
            }
        }

        if(u.getUserType() == 0){
            // 添加角色
            UserRole userRole = new UserRole().setUserId(user.getId()).setRoleId(11L);
            userRoleService.save(userRole);
        }

        //创建认证表
        if(usertype== 0){
            CompanyUser companyUser = new CompanyUser();
            companyUser.setUserId(user.getId());
            companyUserService.save(companyUser);
        }

        if(usertype == 1) {
            DriverUser driverUser=new DriverUser();
            driverUser.setUserId(user.getId());
            driverUserService.save(driverUser);
        }

        // 发送创建账号消息
        addMessage.addSendMessage(user.getId());
        return ResultUtil.success("添加成功");
    }

    @RequestMapping(value = "/admin/edit", method = RequestMethod.POST)
    @ApiOperation(value = "管理员修改资料", notes = "需要通过id获取原用户信息 需要username更新缓存")
    @SystemLog(description = "管理员修改资料", type = LogType.OPERATION)
    @CacheEvict(key = "#u.username")
    public Result<Object> edit(User u,
                               @RequestParam(required = false) Long[] roleIds) {

        User old = userService.get(u.getId());
        u.setUsername(old.getUsername());
        u.setCreateBy(old.getCreateBy());
        u.setCreateTime(old.getCreateTime());
        // 若修改了手机和邮箱判断是否唯一
        if (old.getMobile() != null && !old.getMobile().equals(u.getMobile())
                && userService.findByMobile(u.getMobile()) != null) {
            return ResultUtil.error("该手机号已绑定其他账户");
        }
        if (null != u.getDepartmentId()) {
            Department d = departmentService.get(u.getDepartmentId());
            if (d != null) {
                u.setDepartmentTitle(d.getTitle());
            }
        } else {
            u.setDepartmentId(null);
            u.setDepartmentTitle("");
        }
        u.setPassword(old.getPassword());
        userService.update(u);
        // 删除该用户角色
        userRoleService.deleteByUserId(u.getId());
        if (roleIds != null) {
            // 新角色
            List<UserRole> userRoles = Arrays.asList(roleIds).stream().map(e -> {
                return new UserRole().setRoleId(e).setUserId(u.getId());
            }).collect(Collectors.toList());
            userRoleService.saveOrUpdateAll(userRoles);
        }
        // 手动删除缓存
        redisTemplate.delete("userRole::" + u.getId());
        redisTemplate.delete("userRole::depIds::" + u.getId());
        redisTemplate.delete("permission::userMenuList::" + u.getId());
        return ResultUtil.success("修改成功");
    }

    @RequestMapping(value = "/admin/appdisable", method = RequestMethod.POST)
    @ApiOperation(value = "APP禁用用户")
    @SystemLog(description = "APP禁用用户", type = LogType.OPERATION)
    public Result<Object> appdisable(Long userId) {

        User user = userService.get(userId);
        user.setStatus(CommonConstant.USER_STATUS_LOCK);
        userService.update(user);
        // 手动更新缓存

        // 删除当前用户登录accessToken
        String oldToken = redisTemplate.get(SecurityConstant.USER_TOKEN + user.getUsername());
        if (StrUtil.isNotBlank(oldToken)) {
            redisTemplate.delete(SecurityConstant.TOKEN_PRE + oldToken);
            redisTemplate.delete(SecurityConstant.USER_TOKEN + user.getUsername());
        }

//        String token = redisTemplate.get(SecurityConstant.USER_TOKEN + user.getUsername());
//        if(token!=null){
//            redisTemplate.delete(token);
//        }
        // 删除当前用户授权第三方应用的access_token
        redisTemplate.deleteByPattern(OAuthConstant.OAUTH_TOKEN_PRE + user.getUsername() + "::*");
        redisTemplate.deleteByPattern(OAuthConstant.OAUTH_REFRESH_TOKEN_PRE + user.getUsername() + "::*");

        return ResultUtil.success("操作成功");
    }

    @RequestMapping(value = "/admin/disable/{userId}", method = RequestMethod.POST)
    @ApiOperation(value = "后台禁用用户")
    @SystemLog(description = "后台禁用用户", type = LogType.OPERATION)
    public Result<Object> disable(@ApiParam("用户唯一id标识") @PathVariable Long userId) {

        User user = userService.get(userId);
        user.setStatus(CommonConstant.USER_STATUS_LOCK);
        userService.update(user);
        // 手动更新缓存

        // 删除当前用户登录accessToken
        String oldToken = redisTemplate.get(SecurityConstant.USER_TOKEN + user.getUsername());
        if (StrUtil.isNotBlank(oldToken)) {
            redisTemplate.delete(SecurityConstant.TOKEN_PRE + oldToken);
            redisTemplate.delete(SecurityConstant.USER_TOKEN + user.getUsername());
        }

//        String token = redisTemplate.get(SecurityConstant.USER_TOKEN + user.getUsername());
//        if(token!=null){
//            redisTemplate.delete(token);
//        }
        // 删除当前用户授权第三方应用的access_token
        redisTemplate.deleteByPattern(OAuthConstant.OAUTH_TOKEN_PRE + user.getUsername() + "::*");
        redisTemplate.deleteByPattern(OAuthConstant.OAUTH_REFRESH_TOKEN_PRE + user.getUsername() + "::*");

        return ResultUtil.success("操作成功");
    }


    @RequestMapping(value = "/admin/enable/{userId}", method = RequestMethod.POST)
    @ApiOperation(value = "后台启用用户")
    public Result<Object> enable(@ApiParam("用户唯一id标识") @PathVariable Long userId) {

        User user = userService.get(userId);
        user.setStatus(CommonConstant.USER_STATUS_NORMAL);
        userService.update(user);
        // 手动更新缓存
        redisTemplate.delete(USER + user.getUsername());
        return ResultUtil.success("操作成功");
    }

    @RequestMapping(value = "/delByIds", method = RequestMethod.POST)
    @ApiOperation(value = "批量通过ids删除")
    public Result<Object> delAllByIds(@RequestParam Long[] ids) {
        for (Long id : ids) {
            User u = userService.get(id);
            // 删除相关缓存
            redisTemplate.delete(USER + u.getUsername());
            redisTemplate.delete("userRole_" + u.getId());
            redisTemplate.delete("userRole::depIds:" + u.getId());
            redisTemplate.delete("permission::userMenuList:" + u.getId());
            redisTemplate.deleteByPattern("department::*");
            userService.delete(id);
            // 删除关联角色
            userRoleService.deleteByUserId(id);
            // 删除关联部门负责人
            departmentHeaderService.deleteByUserId(id);
        }
        return ResultUtil.success("批量通过id删除数据成功");
    }

    @RequestMapping(value = "/importData", method = RequestMethod.POST)
    @ApiOperation(value = "导入用户数据")
    public Result<Object> importData(@RequestBody List<User> users) {

        List<Integer> errors = new ArrayList<>();
        List<String> reasons = new ArrayList<>();
        int count = 0;
        for (User u : users) {
            count++;
            // 验证用户名密码不为空
            if (StrUtil.isBlank(u.getUsername()) || StrUtil.isBlank(u.getPassword())) {
                errors.add(count);
                reasons.add("用户名或密码为空");
                continue;
            }
            // 验证用户名唯一
            if (userService.findByUsername(u.getUsername()) != null) {
                errors.add(count);
                reasons.add("用户名已存在");
                continue;
            }
            // 加密密码
            u.setPassword(new BCryptPasswordEncoder().encode(u.getPassword()));
            // 验证部门id正确性
            if (null != u.getDepartmentId()) {
                try {
                    Department d = departmentService.get(u.getDepartmentId());
                    log.info(d.toString());
                } catch (Exception e) {
                    errors.add(count);
                    reasons.add("部门id不存在");
                    continue;
                }
            }
            if (u.getStatus() == null) {
                u.setStatus(CommonConstant.USER_STATUS_NORMAL);
            }
            userService.save(u);
            // 分配默认角色
            if (u.getDefaultRole() != null && u.getDefaultRole() == 1) {
                List<Role> roleList = roleService.findByDefaultRole(true);
                if (roleList != null && roleList.size() > 0) {
                    for (Role role : roleList) {
                        UserRole ur = new UserRole().setUserId(u.getId()).setRoleId(role.getId());
                        userRoleService.save(ur);
                    }
                }
            }
        }
        // 批量保存数据
        int successCount = users.size() - errors.size();
        String successMessage = "全部导入成功，共计 " + successCount + " 条数据";
        String failMessage = "导入成功 " + successCount + " 条，失败 " + errors.size() + " 条数据。<br>" +
                "第 " + errors.toString() + " 行数据导入出错，错误原因分别为：<br>" + reasons.toString();
        String message = "";
        if (errors.isEmpty()) {
            message = successMessage;
        } else {
            message = failMessage;
        }
        return ResultUtil.success(message);
    }

    /**
     * 校验
     *
     * @param username 用户名 不校验传空字符或null 下同
     * @param mobile   手机号
     */
    public void checkUserInfo(String username, String mobile) {

        // 禁用词
        StopWordsUtil.matchWord(username);

        if (StrUtil.isNotBlank(username) && userService.findByUsername(username) != null) {
            throw new FreightException("该登录账号已被注册");
        }

        if (StrUtil.isNotBlank(mobile) && userService.findByMobile(mobile) != null) {
            throw new FreightException("该手机号已被注册");
        }
    }

    /**
     * 校验
     *
     * @param mobile 手机号
     */
    public void checkUserInfo(String mobile) {

        if (StrUtil.isNotBlank(mobile) && userService.findByMobile(mobile) != null) {
            throw new FreightException("该手机号已被注册");
        }
    }

    /**
     * 用户统计接口
     * @return
     */
    @RequestMapping(value = "/userStatistics", method = RequestMethod.GET)
    @ApiOperation(value = "获取当前用户统计接口")
    public Result<UserStatistics> getUserStatInfo() {
        //获取当前用户统计
        UserStatistics res = userService.getCurrentUserStatistics();
        return new ResultUtil<UserStatistics>().setData(res);
    }


    /**
     * 待审核用户接口
     * @return
     */
    @RequestMapping(value = "/pendingUser", method = RequestMethod.GET)
    @ApiOperation(value = "获取待审核用户接口")
    public Result<List<User>> getPendingUser() {
        List<User> res = userService.getPendingUser();
        return new ResultUtil<List<User>>().setData(res);
    }

}
